package cn.turboinfo.fuyang.api.provider.common.service.impl.role;

import cn.turboinfo.fuyang.api.domain.common.service.role.RolePermissionService;
import cn.turboinfo.fuyang.api.entity.admin.exception.user.RolePermissionException;
import cn.turboinfo.fuyang.api.entity.admin.pojo.role.RolePermission;
import cn.turboinfo.fuyang.api.entity.admin.pojo.role.RolePermissionCreator;
import cn.turboinfo.fuyang.api.entity.admin.pojo.role.RolePermissionUpdater;
import cn.turboinfo.fuyang.api.provider.common.repository.database.role.RolePermissionDAO;
import cn.turboinfo.fuyang.api.provider.common.repository.database.role.RolePermissionPO;
import net.sunshow.toolkit.core.qbean.api.request.QPage;
import net.sunshow.toolkit.core.qbean.api.request.QRequest;
import net.sunshow.toolkit.core.qbean.api.response.QResponse;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanCreatorHelper;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanUpdaterHelper;
import net.sunshow.toolkit.core.qbean.helper.service.impl.AbstractQServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@Service
public class RolePermissionServiceImpl extends AbstractQServiceImpl<RolePermission> implements RolePermissionService {
    private RolePermissionDAO rolePermissionDAO;

    @Override
    public Optional<RolePermission> getById(Long id) {
        return rolePermissionDAO.findById(id).map(this::convertQBean);
    }

    @Override
    @Transactional
    public RolePermission save(RolePermissionCreator creator) throws RolePermissionException {
        RolePermissionPO rolePermissionPO = new RolePermissionPO();

        QBeanCreatorHelper.copyCreatorField(rolePermissionPO, creator);

        return convertQBean(rolePermissionDAO.save(rolePermissionPO));
    }

    @Override
    @Transactional
    public RolePermission update(RolePermissionUpdater updater) throws RolePermissionException {
        RolePermissionPO rolePermissionPO = getEntityWithNullCheckForUpdate(updater.getUpdateId(), rolePermissionDAO);

        QBeanUpdaterHelper.copyUpdaterField(rolePermissionPO, updater);

        return convertQBean(rolePermissionPO);
    }

    @Override
    public QResponse<RolePermission> findAll(QRequest request, QPage requestPage) {
        return convertQResponse(findAllInternal(request, requestPage));
    }

    private Page<RolePermissionPO> findAllInternal(QRequest request, QPage requestPage) {
        return rolePermissionDAO.findAll(convertSpecification(request), convertPageable(requestPage));
    }

    @Override
    public List<RolePermission> findByRoleId(Long roleId) {
        return rolePermissionDAO.findByRoleId(roleId).stream().map(this::convertQBean).collect(Collectors.toList());
    }

    @Override
    public List<RolePermission> findByRoleIdCollection(Collection<Long> roleIdCollection) {
        return rolePermissionDAO.findByRoleIdIn(roleIdCollection).stream().map(this::convertQBean).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void reassign(Long roleId, Collection<Long> permissionIdCollection) {
        // 拿到已有的
        List<RolePermissionPO> rolePermissionPOList = rolePermissionDAO.findByRoleId(roleId);

        Map<Long, RolePermissionPO> permissionIdRolePermissionPOMap = rolePermissionPOList.stream().collect(Collectors.toMap(RolePermissionPO::getPermissionId, Function.identity()));

        // 要删除的部分
        rolePermissionPOList.stream().map(RolePermissionPO::getPermissionId).filter(permissionId -> !permissionIdCollection.contains(permissionId)).forEach(permissionId -> {
            // 执行删除
            rolePermissionDAO.delete(permissionIdRolePermissionPOMap.get(permissionId));
        });

        // 要新增的部分
        permissionIdCollection.stream()
                .filter(permissionId -> !permissionIdRolePermissionPOMap.containsKey(permissionId))
                .map(permissionId -> {
                    RolePermissionPO po = new RolePermissionPO();
                    po.setRoleId(roleId);
                    po.setPermissionId(permissionId);
                    return po;
                })
                .forEach(po -> rolePermissionDAO.save(po));
    }

    @Override
    protected Supplier<? extends RuntimeException> getExceptionSupplier(String message,
                                                                        Throwable cause) {
        return () -> new RolePermissionException(message, cause);
    }

    @Autowired
    public void setRolePermissionDAO(RolePermissionDAO rolePermissionDAO) {
        this.rolePermissionDAO = rolePermissionDAO;
    }
}
